#ifndef DEF_LECTEUR_HPP
#define DEF_LECTEUR_HPP

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <fstream>
#include <vector>
#include <map>
#include <time.h>

class Box
{
  public :
        static const char* nomMnt;
        static const char* nomPt;
        static const char* nomTmp;
};

class FileManager
{
private :

  static FileManager * _me;
  unsigned int _lignes;
  unsigned int _nblig;
  unsigned int _nbcol;
  int _novalue;
  std::ifstream * fichiersource;
  int cptfrag;

  FileManager();
  FileManager(std::string chaine);

public :

  static FileManager * get();
  static FileManager * get(std::string chaine);

  static void destroy();

    ~FileManager();
  /**
     vector<unsigned int> *tab   : tableau vide dans lequel seront stockees les hauteurs de la ligne demandee du mnt
     const char* nomFic : nom du fichier a etudier
     unsigned int line : ligne du fichier a etudier. Attention : commence a la ligne 0
        return true si tout cest correctement deroule
        return false en cas derreur. Le vector nest pas nettoye en cas derreur
    **/
    bool getLine(int *tab, unsigned int line, const char * fic);

    /**
        vector<unsigned int> *tab   : tableau dans lequel sont stockees les valeurs a ajouter en fin de fichier
        const char* nomFic : nom du fichier a completer
        return true si tout cest correctement deroule
        return false en cas derreur. Le vector nest pas nettoye en cas derreur
    **/
    bool addLine(int *tab);

    /**
        std::map<unsigned int, unsigned int> mymap : map des valeurs a echanger pour la maj
        ex : map<unsigned int, unsigned int> mymap; mymap[0]=5; mymap[15]=6; booleen=fm->switchVal(mymap);
             remplace tout les puits du bassin 0 par bassin 5 et du bassin 15 par 6
        return true si tout c'est correctement deroule
        return false en cas d'erreur.
    **/
    bool switchVal(std::map<int, int> &mymap);

    /**
        bool b : true -> binaire vers texte, false -> texte vers binaire
        string binary & string mnt : nom respectifs des fichiers binaires et mnt
            /!\ le fichier binaire nest pas cree sil nexiste pas, meme vide
    **/
    void translate(bool b, std::string binary, std::string mnt);

    /**
        std::vector<unsigned int> *tab : tableau vide dans lequel seront stockees les hauteurs de la ligne suivante du mnt passe au constructeur (bassin.mnt par defaut)
        return true si tout cest correctement deroule
        return false en cas derreur. Le vector nest pas nettoye en cas derreur
    **/
    bool getNextLine(int *tab);

    unsigned int getNbLig(){return _nblig;}
    unsigned int getNbCol(){return _nbcol;}
    int getNoValue(){return _novalue;}
    void fragincr(){cptfrag++;}

	void controle(std::string a, std::string b);

    void majmap(std::map<int,int> & mymap);
	void stockMap(std::map<int,int> & mymap);
	void defragmap();
};

//vector[0]
struct lolilol
{
    unsigned int a;
    unsigned int b;
    unsigned int c;
    unsigned int d;
    unsigned int e;
    int f;
};

inline FileManager::FileManager(std::string chaine)
{
    cptfrag = 0;
    _me = this;
    _lignes=0;
    fichiersource = new std::ifstream(chaine.c_str(), std::ios::in | std::ios::binary);
    lolilol tip;
    fichiersource->read((char*)&tip, sizeof(tip));
    _nblig=tip.b;
    _nbcol=tip.a;
    _novalue=tip.f;
    std::string cmd = (std::string)"del "+(std::string)Box::nomPt;
    system(cmd.c_str());

    std::ofstream out;
    out.open(Box::nomPt,std::ios_base::out | std::ios_base::trunc);
    out.close();

    std::fstream fichier(Box::nomPt, std::ios::in | std::ios::out| std::ifstream::binary);
    if(fichier)
    {
        fichier.write((char*)&tip,sizeof(tip));
    }
    fichier.close();
    out.open("tempo",std::ios_base::out | std::ios_base::trunc);
    out.close();
    out.open("defrag",std::ios_base::out | std::ios_base::trunc);
    out.close();
    out.open("defragfinal",std::ios_base::out | std::ios_base::trunc);
    out.close();
}

inline FileManager * FileManager::get()
{
    if(!_me)
        _me = new FileManager();
    return _me;
}

inline FileManager * FileManager::get(std::string chaine)
{
    if(!_me)
        _me = new FileManager(chaine);
    return _me;
}

inline FileManager::~FileManager()
{
    fichiersource->close();
    delete fichiersource;
}

inline void FileManager::destroy()
{
    delete _me;
}

#endif //DEF_LECTEUR_HPP

